Introducción
Analizar texto se ha convertido en una destreza que permite descubrir características y a la vez entender a los creadores del texto. Por ejemplo, podemos analizar el texto determinando las palabras más frecuentes, realizar un análisis de sentimientos y clasificar el contenido por clases, determinar la relación entre usuarios de redes sociales, entre otros.
Los datos
Utilizando Developer Platform de Twitter se procedió a crear la conexión para realizar búsquedas de información relacionada con líderes socialistas latinoamericanos que han gobernado o han participado en elecciones durante los últimos 20 años. El paquete utilizado para este fin es rtweet. Salvo una excepción, se realizó una doble búsqueda por cada líder, para esto se utilizó a get_timeline del paquete rtweet. Obtenidos los datos se realizó una selección de campos con el fin de realizar un análisis de tweets propios y retweets.
Los líderes seleccionados son:
| 1 |
Andrés Arauz |
ecuarauz |
Ecuador |
| 2 |
Alberto Fernández |
alferdez |
Argentina |
| 3 |
Andrés Manuel |
lopezobrador_ |
México |
| 4 |
Cristina Kirchner |
CFKArgentina |
Argentina |
| 5 |
Miguel Díaz-Canel Bermúdez |
DiazCanelB |
Cuba |
| 6 |
Dilma Rousseff |
dilmabr |
Brasil |
| 7 |
Ernesto Samper |
ernestosamperp |
Colombia |
| 8 |
Evo Morales |
evoespueblo |
Bolivia |
| 9 |
Fernando Lugo |
lugo_py |
Paraguay |
| 10 |
Gabriel Boric |
gabrielboric |
Chile |
| 11 |
Gustavo Petro |
petrogustavo |
Colombia |
| 12 |
Hugo Chávez |
chavezcandanga |
Venezuela |
| 13 |
Luis Arce |
LuchoXBolivia |
Bolivia |
| 14 |
Lula |
LulaOficial |
Brasil |
| 15 |
Manuel Zelaya |
manuelzr |
Honduras |
| 16 |
Nicolás Maduro |
NicolasMaduro |
Venezuela |
| 17 |
Ollanta Humala |
Ollanta_HumalaT |
Perú |
| 18 |
Pedro Castillo |
PedroCastilloTe |
Perú |
| 19 |
Rafael Correa |
MashiRafael |
Ecuador |
| 20 |
Xiomara Castro de Zelaya |
XiomaraCastroZ |
Honduras |
Dependiendo del análisis se consideró a todos los usuarios como uno solo, sin embargo, lo ideal es trabajar por separado para cada usuario para determinar las diferencias y similitudes que puedan existir. Los datos recopilados cuentan con 58512 registros que entre sus principales características permiten determinar si un tweet es propio o retweet.
A continuación, la carga de los datos y la visualización de los primeros registros:
Palabras más usadas
Otras descripciones usuales son determinar la cantidad de palabras utilizadas, las palabras más populares y su representación. Para realizarlas, es importante limpiar a los datos, para esto se seleccionó a los paquetes tidytext y tm. El procedimiento es iniciar removiendo caracteres que no tengan un significado concreto. Se ha seguido el siguiente orden: remover hipervínculos, remover menciones, remover separadores, remover números y remover espacios en blanco. Luego, es importante remover acentos y cambiar todas las letras a minúsculas o mayúsculas.
library(tidytext)
library(tm)
Loading required package: NLP
Attaching package: ‘NLP’
The following object is masked from ‘package:ggplot2’:
annotate
palabras <- tweets_propio %>%
filter(is_retweet == FALSE) %>%
select(text) %>%
mutate(text=str_replace_all(text, "https\\S*", "")) %>% #remover hipervínculos
mutate(text=str_replace_all(text, "@\\S*", "")) %>% #remover menciones
mutate(text=str_replace_all(text, "[\r\n\t]", "")) %>% #remover separadores
mutate(text=removeNumbers(text)) %>% #remover números
mutate(text=removePunctuation(text)) %>% #remover puntuacion
mutate(text=str_squish(text)) %>% #remover espacios en blanco
mutate(text=tolower(text)) #a minúsculas
Con el texto limpio, se procede a realizar la tokenización. Esto significa que vamos a dividir a cada tweet en unidades de texto, en este caso en palabras. Existe una interesante teoría al respecto, ya que si se desea las unidades pueden ser dos palabras seguidas u oraciones, por ejemplo, si alguien se interesa puede leer al respecto en el capítulo 1 de Text Mining with R: A Tidy Approach.
palabras <- palabras %>%
unnest_tokens(word, text, to_lower = F) #tokenizacion
palabras
Al visualizar las primeras palabras obtenidas en el dataframe palabras se observan palabras como “la”, “de”, “es”, entre otras, que llaman la atención ya que uno esperaría que aparezcan muchas veces en un determinado texto. Una práctica común es remover a este tipo de palabras, denominadas stopwords. En la documentación de los paquetes utilizados se puede aprender un poco más al respecto. En este caso, al contar con usuarios que hablan español, inglés y portugués se removieron stopwords para estos tres idiomas. Además, se contabilizó a cada palabra y ordenó en forma descendente considerando el número de apariciones.
palabras <- palabras %>%
filter(!word %in% stopwords("spanish")) %>%
filter(!word %in% stopwords("portuguese")) %>%
filter(!word %in% stopwords("english")) %>%
count(word, sort = TRUE) %>%
mutate(word = reorder(word, n)) %>%
arrange(desc(n))
palabras
Observemos que las palabras “é” y “ser” aparecen, esto es algo que en principio no esperamos suceda, sin embargo, aprovechamos su aparición para indicar como remover palabras especiales. Simplemente se determina un nuevo conjunto de palabras a ser removidas, en este caso solamente se consideró a las palabras mencionadas antes, pero si se trabaja con algún otro texto que incluya muchos símbolos o palabras especiales como variables con subíndices, el considerar está opción puede ser de gran utilidad.
my_stopword <- tibble(word = c("é", "ser"))
palabras <- palabras %>%
anti_join(my_stopword)
Joining, by = "word"
palabras
Para finalizar, se creó una nube de palabras que es una herramienta visual muy amigable que permite determinar por el tamaño de la palabra su importancia ya que representa así su frecuencia de aparición. Para esto se utilizó al paquete wordcloud2 que cuenta con características que permiten realizar nubes muy amigables. Por ejemplo, usar un fondo gris, colores pastel para las palabras y darle una forma de corazón.
library(wordcloud2)
Registered S3 methods overwritten by 'htmltools':
method from
print.html tools:rstudio
print.shiny.tag tools:rstudio
print.shiny.tag.list tools:rstudio
Registered S3 method overwritten by 'htmlwidgets':
method from
print.htmlwidget tools:rstudio
palabras %>%
select(word, freq=n) %>%
wordcloud2(shape = 'cardioid', size = 0.25, color = "random-light", backgroundColor = "grey")
El fin de este archivo y los que vendrán es compartir lo que he aprendido. Es posible hacer análisis más profundos y detallados que espero seguir compartiendo, por ejemplo, el realizar un análisis de sentimientos y un clasificador basado en un análisis de sentimientos.
Elaborado por Jairo Rojas.
LS0tDQp0aXRsZTogIkFuw6FsaXNpcyBkZSB0ZXh0byBjb24gUiINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCiMgSW50cm9kdWNjacOzbg0KDQpBbmFsaXphciB0ZXh0byBzZSBoYSBjb252ZXJ0aWRvIGVuIHVuYSBkZXN0cmV6YSBxdWUgcGVybWl0ZSBkZXNjdWJyaXIgY2FyYWN0ZXLDrXN0aWNhcyB5IGEgbGEgdmV6IGVudGVuZGVyIGEgbG9zIGNyZWFkb3JlcyBkZWwgdGV4dG8uIFBvciBlamVtcGxvLCBwb2RlbW9zIGFuYWxpemFyIGVsIHRleHRvIGRldGVybWluYW5kbyBsYXMgcGFsYWJyYXMgbcOhcyBmcmVjdWVudGVzLCByZWFsaXphciB1biBhbsOhbGlzaXMgZGUgc2VudGltaWVudG9zIHkgY2xhc2lmaWNhciBlbCBjb250ZW5pZG8gcG9yIGNsYXNlcywgZGV0ZXJtaW5hciBsYSByZWxhY2nDs24gZW50cmUgdXN1YXJpb3MgZGUgcmVkZXMgc29jaWFsZXMsIGVudHJlIG90cm9zLg0KDQojIExvcyBkYXRvcw0KDQpVdGlsaXphbmRvIFtEZXZlbG9wZXIgUGxhdGZvcm1dKGh0dHBzOi8vZGV2ZWxvcGVyLnR3aXR0ZXIuY29tKSBkZSBbVHdpdHRlcl0oaHR0cHM6Ly90d2l0dGVyLmNvbSkgc2UgcHJvY2VkacOzIGEgY3JlYXIgbGEgY29uZXhpw7NuIHBhcmEgcmVhbGl6YXIgYsO6c3F1ZWRhcyBkZSBpbmZvcm1hY2nDs24gcmVsYWNpb25hZGEgY29uIGzDrWRlcmVzIHNvY2lhbGlzdGFzIGxhdGlub2FtZXJpY2Fub3MgcXVlIGhhbiBnb2Jlcm5hZG8gbyBoYW4gcGFydGljaXBhZG8gZW4gZWxlY2Npb25lcyBkdXJhbnRlIGxvcyDDumx0aW1vcyAyMCBhw7Fvcy4gRWwgcGFxdWV0ZSB1dGlsaXphZG8gcGFyYSBlc3RlIGZpbiBlcyBbcnR3ZWV0XShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvcnR3ZWV0KS4gU2Fsdm8gdW5hIGV4Y2VwY2nDs24sIHNlIHJlYWxpesOzIHVuYSBkb2JsZSBiw7pzcXVlZGEgcG9yIGNhZGEgbMOtZGVyLCBwYXJhIGVzdG8gc2UgdXRpbGl6w7MgYSAqZ2V0X3RpbWVsaW5lKiBkZWwgcGFxdWV0ZSBbcnR3ZWV0XShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvcnR3ZWV0KS4gT2J0ZW5pZG9zIGxvcyBkYXRvcyBzZSByZWFsaXrDsyB1bmEgc2VsZWNjacOzbiBkZSBjYW1wb3MgY29uIGVsIGZpbiBkZSByZWFsaXphciB1biBhbsOhbGlzaXMgZGUgdHdlZXRzIHByb3Bpb3MgeSByZXR3ZWV0cy4NCg0KTG9zIGzDrWRlcmVzIHNlbGVjY2lvbmFkb3Mgc29uOg0KDQp8ICoqTm8uKiogfCAqKk5vbWJyZXMqKiB8ICoqVXN1YXJpbyoqIHwgKipQYcOtcyoqfA0KfC0tLS0tLS18LS0tLS0tLXwtLS0tLS0tfC0tLS0tLS18DQp8IDEgfCBBbmRyw6lzIEFyYXV6IHwgZWN1YXJhdXogfCBFY3VhZG9yfA0KfCAyIHwgQWxiZXJ0byBGZXJuw6FuZGV6IHwgYWxmZXJkZXogfCBBcmdlbnRpbmF8DQp8IDMgfCBBbmRyw6lzIE1hbnVlbCB8IGxvcGV6b2JyYWRvcl8gfCBNw6l4aWNvfA0KfCA0IHwgQ3Jpc3RpbmEgS2lyY2huZXIgfCBDRktBcmdlbnRpbmEgfCBBcmdlbnRpbmF8DQp8IDUgfCBNaWd1ZWwgRMOtYXotQ2FuZWwgQmVybcO6ZGV6IHwgRGlhekNhbmVsQiB8IEN1YmF8DQp8IDYgfCBEaWxtYSBSb3Vzc2VmZiB8IGRpbG1hYnIgfCBCcmFzaWx8DQp8IDcgfCBFcm5lc3RvIFNhbXBlciB8IGVybmVzdG9zYW1wZXJwIHwgQ29sb21iaWF8DQp8IDggfCBFdm8gTW9yYWxlcyB8IGV2b2VzcHVlYmxvIHwgQm9saXZpYXwNCnwgOSB8IEZlcm5hbmRvIEx1Z28gfCBsdWdvX3B5IHwgUGFyYWd1YXl8DQp8IDEwIHwgR2FicmllbCBCb3JpYyB8IGdhYnJpZWxib3JpYyB8IENoaWxlfA0KfCAxMSB8IEd1c3Rhdm8gUGV0cm8gfCBwZXRyb2d1c3Rhdm8gfCBDb2xvbWJpYXwNCnwgMTIgfCBIdWdvIENow6F2ZXogfCBjaGF2ZXpjYW5kYW5nYSB8IFZlbmV6dWVsYXwNCnwgMTMgfCBMdWlzIEFyY2UgfCBMdWNob1hCb2xpdmlhIHwgQm9saXZpYXwNCnwgMTQgfCBMdWxhIHwgTHVsYU9maWNpYWwgfCBCcmFzaWx8DQp8IDE1IHwgTWFudWVsIFplbGF5YSB8IG1hbnVlbHpyIHwgSG9uZHVyYXN8DQp8IDE2IHwgTmljb2zDoXMgTWFkdXJvIHwgTmljb2xhc01hZHVybyB8IFZlbmV6dWVsYXwNCnwgMTcgfCBPbGxhbnRhIEh1bWFsYSB8IE9sbGFudGFfSHVtYWxhVCB8IFBlcsO6fA0KfCAxOCB8IFBlZHJvIENhc3RpbGxvIHwgUGVkcm9DYXN0aWxsb1RlIHwgUGVyw7p8DQp8IDE5IHwgUmFmYWVsIENvcnJlYSB8IE1hc2hpUmFmYWVsIHwgRWN1YWRvcnwNCnwgMjAgfCBYaW9tYXJhIENhc3RybyBkZSBaZWxheWEgfCBYaW9tYXJhQ2FzdHJvWiB8IEhvbmR1cmFzfA0KDQpEZXBlbmRpZW5kbyBkZWwgYW7DoWxpc2lzIHNlIGNvbnNpZGVyw7MgYSB0b2RvcyBsb3MgdXN1YXJpb3MgY29tbyB1bm8gc29sbywgc2luIGVtYmFyZ28sIGxvIGlkZWFsIGVzIHRyYWJhamFyIHBvciBzZXBhcmFkbyBwYXJhIGNhZGEgdXN1YXJpbyBwYXJhIGRldGVybWluYXIgbGFzIGRpZmVyZW5jaWFzIHkgc2ltaWxpdHVkZXMgcXVlIHB1ZWRhbiBleGlzdGlyLiBMb3MgZGF0b3MgcmVjb3BpbGFkb3MgY3VlbnRhbiBjb24gNTg1MTIgcmVnaXN0cm9zIHF1ZSBlbnRyZSBzdXMgcHJpbmNpcGFsZXMgY2FyYWN0ZXLDrXN0aWNhcyBwZXJtaXRlbiBkZXRlcm1pbmFyIHNpIHVuIHR3ZWV0IGVzIHByb3BpbyBvIHJldHdlZXQuDQoNCkEgY29udGludWFjacOzbiwgbGEgY2FyZ2EgZGUgbG9zIGRhdG9zIHkgbGEgdmlzdWFsaXphY2nDs24gZGUgbG9zIHByaW1lcm9zIHJlZ2lzdHJvczoNCg0KYGBge3IsIGVjaG89RkFMU0V9DQp0d2VldHMgPC0gZGF0b3MNCmhlYWQodHdlZXRzKQ0KYGBgDQoNCg0KIyBEZXNjcmlwY2nDs24gIGRlbCB0aXBvIGRlIHR3ZWV0Lg0KDQpFbCBjYW1wbyB0ZXh0byBhbG1hY2VuYSBhIGNhZGEgdHdlZXQgcmVjb3BpbGFkbywgZXMgaW1wb3J0YW50ZSBub3RhciBxdWUgdW4gdHdlZXQgcHVlZGUgc2VyIGRlIGF1dG9yw61hIHByb3BpYSBvIG5vLCBlbiBlc3RlIGNhc28gaGFibGFtb3MgZGUgdW4gcmV0d2VldC4gUGFyYSBlc3RvIHNlIHV0aWxpesOzIGFsIHBhcXVldGUgW3RpZHl2ZXJzZV0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3RpZHl2ZXJzZS8pIHF1ZSBkZWJlcyBhcHJlbmRlciBzaSB0ZSBpbnRlcmVzYSBtYW5pcHVsYXIgZGF0b3MgY29uIFtSXShodHRwczovL3d3dy5yLXByb2plY3Qub3JnLykuIEEgY29udGludWFjacOzbiwgbGEgY2FudGlkYWQgZGUgdHdlZXRzIHBvciB0aXBvIHkgcG9yIHVzdWFyaW86DQoNCmBgYHtyLCB3YXJuaW5nPUZBTFNFfQ0KbGlicmFyeSh0aWR5dmVyc2UpDQoNCm1lcmdlKHggPSB0d2VldHMgJT4lICN0d2VldHMgcHJvcGlvcw0KICAgICAgICBzZWxlY3Qoc2NyZWVuX25hbWUsIGlzX3JldHdlZXQpICU+JSAjc2VsZWNjacOzbiBkZSBjYW1wb3MNCiAgICAgICAgZmlsdGVyKGlzX3JldHdlZXQgPT0gRkFMU0UpICU+JSAjZmlsdHJvIHBhcmEgdHdlZXQgcHJvcGlvDQogICAgICAgIGNvdW50KHNjcmVlbl9uYW1lLCBuYW1lID0gIm5fcHJvcGlvcyIpLCAjY2FudGlkYWQgZGUgdHdlZXRzIHByb3Bpb3MNCiAgICAgIHkgPSB0d2VldHMgJT4lICAjcmV0d2VldHMNCiAgICAgICAgc2VsZWN0KHNjcmVlbl9uYW1lLCBpc19yZXR3ZWV0KSAlPiUgI3NlbGVjY2nDs24gZGUgY2FtcG9zDQogICAgICAgIGZpbHRlcihpc19yZXR3ZWV0ID09IFRSVUUpICU+JSAjZmlsdHJvIHBhcmEgcmV0d2VldA0KICAgICAgICBjb3VudChzY3JlZW5fbmFtZSwgbmFtZSA9ICJuX3JldHdlZXRzIiksICNjYW50aWRhZCBkZSByZXR3ZWV0cw0KICAgICAgYWxsID0gVFJVRSkgJT4lICN1bmnDs24gZGUgZGF0YWZyYW1lcw0KICBhcnJhbmdlKHNjcmVlbl9uYW1lKSAjb3JkZW4gcG9yIHNjcmVlbl9uYW1lDQpgYGANCkJhc2FkbyBlbiBlbCByZXN1bHRhZG8gYW50ZXJpb3IsIGV4aXN0ZW4gdXN1YXJpb3MgcXVlIG5vIHJlYWxpemFuIHJldHdlZXRzLCBlbnRvbmNlcyBzZSBhbmFsaXphIG51ZXZhbWVudGUgYSB0b2RvcyBsb3MgdXN1YXJpb3MgY29tbyB1bm8gc29sby4gQSBjb250aW51YWNpw7NuLCBsYSBjYW50aWRhZCBkZSB0d2VldHMgcHJvcGlvcyB5IHJldHdlZXRzOg0KDQpgYGB7cn0NCiMgUHJvcGlvcw0KdHdlZXRzX3Byb3BpbyA9IHR3ZWV0cyAlPiUgZmlsdGVyKGlzX3JldHdlZXQ9PUZBTFNFKQ0KIyBSZXR3ZWV0cw0KdHdlZXRzX3JldHdlZXRzID0gdHdlZXRzICU+JSBmaWx0ZXIoaXNfcmV0d2VldD09VFJVRSkNCiMgQ2FudGlkYWQgZGUgdHdlZXRzIHByb3Bpb3MgeSBkZSByZXR3ZWV0cw0KQ2FudGlkYWRUaXBvID0gZGF0YS5mcmFtZSh0aXBvPWMoIlByb3BpbyIsIlJldHdlZXRzIiksICNjYW1wbyB0aXBvIGRlIHR3ZWV0DQogICAgICAgICAgICAgICAgICAgICAgICAgY2FudGlkYWQ9Yyhucm93KHR3ZWV0c19wcm9waW8pLCBucm93KHR3ZWV0c19yZXR3ZWV0cykpICNjYW1wbyBjYW50aWRhZCBkZSBjYWRhIHRpcG8NCiAgICAgICAgICAgICAgICAgICAgICAgICApDQpDYW50aWRhZFRpcG8NCmBgYA0KDQpQYXJhIHZpc3VhbGl6YXIgZXN0w6EgcmVsYWNpw7NuIGludHJvZHVjaW1vcyB1biBwZXNvIGEgY2FkYSB0aXBvLCBlbiBlc3RlIGNhc28gc3UgcG9yY2VudGFqZSwgeSBjcmVhbW9zIHVuIGdyw6FmaWNvIHBvciBibG9xdWVzLiBQYXJhIGVzdG8gc2UgdXRpbGl6YSBhbCBwYXF1ZXRlIFt3YWZmbGVdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy93YWZmbGUvKSBxdWUgZW50cmUgc3VzIGZ1bmNpb25lcyBwZXJtaXRlIHJlYWxpemFyIHVuIGdyw6FmaWNvIHBvciBibG9xdWVzLg0KDQpgYGB7ciAsIHdhcm5pbmc9RkFMU0UsIGVjaG89VFJVRX0NCiMgQXVtZW50YW5kbyBwZXNvIGEgY2FkYSB0aXBvDQpDYW50aWRhZFRpcG8gPSBDYW50aWRhZFRpcG8gJT4lIA0KICBtdXRhdGUocGVzbz1yb3VuZChjYW50aWRhZC9zdW0oY2FudGlkYWQpKjEwMCwwMCkpICU+JSAjQ3JlYWNpb24gZGUgY2FtcG8gcGVzbw0KICBhcnJhbmdlKGRlc2MoY2FudGlkYWQpKSAjb3JkZW5hbmRvIHBvciBjYW50aWRhZA0KDQojIEV4dHJhY2Npb24gZGVsIHBlc28NCnBhcnRlID0gQ2FudGlkYWRUaXBvJHBlc28NCiMgRXRpcXVldGFuZG8gcG9yIGNsYXNlDQpuYW1lcyhwYXJ0ZSkgPSBDYW50aWRhZFRpcG8kdGlwbw0KIyBHcmFmaWNhIGRlIHRpcG8gZGUgdHdlZXQNCmxpYnJhcnkod2FmZmxlKQ0Kd2FmZmxlKHBhcnRlLCANCiAgICAgICByb3dzID0gNSwgI27Dum1lcm8gZGUgZmlsYXMgDQogICAgICAgdGl0bGUgPSAnVGlwbyBkZSB0d2VldHMnLCANCiAgICAgICBjb2xvcnMgPSBjb2xvclJhbXBQYWxldHRlKGMoJ2JsdWUnLCAncmVkJykpKDIpLCAjcGFsZXRhIGRlIGNvbG9yZXMNCiAgICAgICAjICgyKSBpbmRpY2EgZWwgbsO6bWVybyBkZSBjbGFzZXMgcXVlIHZhIGEgZ3JhZmljYXINCiAgICAgICBwYWQgPSAxLCAjZGVuc2lkYWQNCiAgICAgICBzaXplID0gMC41LCAjc2VwYXJhY2lvbiBlbnRyZSBibG9xdWVzICANCiAgICAgICBmbGlwID0gRkFMU0UsI29yaWVudGFjaW9uIHZlcnRpY2FsIGNvbiBUUlVFDQogICAgICAgeGxhYiA9ICAiRnVlbnRlOiBUd2l0dGVyIg0KICAgICAgICkNCmBgYA0KDQpPYnNlcnZhbW9zIHF1ZSBlcyBzdSBtYXlvcsOtYSBzZSBjcmVhbiB0d2VldHMgcHJvcGlvcy4gDQoNCiMgVHdlZXRzIHBvcHVsYXJlcw0KDQpTZSBkZXRlcm1pbmEgZWwgdHdlZXQgcHJvcGlvIG3DoXMgcG9wdWxhciBwb3IgdXN1YXJpbywgaWRlbnRpZmljYW5kbyBhIGxhIGNhbnRpZGFkIGRlIG1lIGd1c3RhIHJlY2liaWRvcy4NCg0KYGBge3J9DQp0d2VldHMgJT4lIA0KICBmaWx0ZXIoaXNfcmV0d2VldCA9PSBGQUxTRSkgJT4lICNmaWx0cm8gcGFyYSB0d2VldCBwcm9waW8NCiAgZ3JvdXBfYnkoc2NyZWVuX25hbWUpICU+JSAjYWdydXBhY2lvbiBwb3Igc2NyZWVuX25hbWUNCiAgbXV0YXRlKHBvcHVsYXIgPSBtYXgoZmF2b3JpdGVfY291bnQpKSAlPiUgI2NyZWFjacOzbiBkZSBjYW1wbw0KICBmaWx0ZXIoZmF2b3JpdGVfY291bnQgPT0gcG9wdWxhcikgJT4lICNmaWx0cm8gcGFyYSBzZWxlY2Npb25hciBhbCB0d2VldCBtw6FzIHBvcHVsYXINCiAgc2VsZWN0KHNjcmVlbl9uYW1lLCBwb3B1bGFyLCB0ZXh0KSAlPiUgIyBzZWxlY2Npw7NuIGRlIGNhbXBvcw0KICBhcnJhbmdlKGRlc2MocG9wdWxhcikpICNvcmRlbiBwb3IgcG9wdWxhcg0KYGBgDQoNCkVsIHJldHdlZXQgIG3DoXMgcG9wdWxhciBwb3IgdXN1YXJpbyB0YW1iacOpbiBlcyBpZGVudGlmaWNhZG8uDQoNCmBgYHtyfQ0KdHdlZXRzICU+JSANCiAgZmlsdGVyKGlzX3JldHdlZXQgPT0gVFJVRSkgJT4lICNmaWx0cm8gcGFyYSByZXR3ZWV0DQogIGdyb3VwX2J5KHNjcmVlbl9uYW1lKSAlPiUgI2FncnVwYWNpb24gcG9yIHNjcmVlbl9uYW1lDQogIG11dGF0ZShwb3B1bGFyID0gbWF4KHJldHdlZXRfZmF2b3JpdGVfY291bnQpKSAlPiUgI2NyZWFjacOzbiBkZSBjYW1wbw0KICBmaWx0ZXIocmV0d2VldF9mYXZvcml0ZV9jb3VudCA9PSBwb3B1bGFyKSAlPiUgI2ZpbHRybyBwYXJhIHNlbGVjY2lvbmFyIGFsIHR3ZWV0IG3DoXMgcG9wdWxhcg0KICBzZWxlY3Qoc2NyZWVuX25hbWUsIHBvcHVsYXIsIHRleHQpICU+JSAjIHNlbGVjY2nDs24gZGUgY2FtcG9zDQogIGFycmFuZ2UoZGVzYyhwb3B1bGFyKSkgI29yZGVuIHBvciBwb3B1bGFyDQpgYGANCg0KIyBBbsOhbGlzaXMgZGUgaGFzaHRhZ3MNCg0KRGVudHJvIGRlIGNhZGEgcHVibGljYWNpw7NuIGVzIGNvbcO6biBhw7FhZGlyIGFsZ8O6biBoYXNodGFnLiBTZSBkZXRlcm1pbsOzIGxvcyAyMCBoYXNodGFncyBtw6FzIHBvcHVsYXJlcyBwb3IgdGlwbyBkZSB0d2VldCBjb25zaWRlcmFuZG8gYSB0b2RvcyBjb21vIHVuby4gUHJpbWVybyBsb3MgaGFzaHRhZ3MgcmVsYWNpb25hZG9zIGNvbiB0d2VldHMgcHJvcGlvcy4NCg0KDQpgYGB7ciwgd2FybmluZz1GQUxTRX0NCnR3ZWV0c19oYXNodGFnIDwtIHR3ZWV0c19wcm9waW8gJT4lIA0KICBmaWx0ZXIoIWlzLm5hKGhhc2h0YWdzKSkgJT4lIA0KICBzZWxlY3QoaGFzaHRhZ3MpDQoNCnRpYmJsZSh3b3JkID0gdW5saXN0KHR3ZWV0c19oYXNodGFnJGhhc2h0YWdzKSkgJT4lICNleHRyYWVyIGhhc2h0YWcNCiAgY291bnQod29yZCwgbmFtZSA9ICJjYW50aWRhZCIsIHNvcnQgPSBUUlVFKSAlPiUgI2NvbnRhciBoYXNodGFncw0KICBoZWFkKDIwKSAlPiUgI3NlbGVjY2lvbmFyIGxvcyAyMCBwcmltZXJvcw0KICBtdXRhdGUod29yZDEgPSByZW9yZGVyKHdvcmQsIGNhbnRpZGFkKSkgJT4lICNvcmRlbmFyDQogIGdncGxvdChhZXMoeCA9IHdvcmQxLCB5ID0gY2FudGlkYWQpKSArICNjcmVhciBsYSBncmFmaWNhDQogIGdlb21fY29sKGNvbG91ciA9ICJ3aGl0ZSIsIGZpbGwgPSAiYmx1ZSIpICsgI2FuYWRlIGxhIGdyw6FmaWNhIGRlIGNhbnRpZGFkDQogIHhsYWIoTlVMTCkgKyAjcXVpdGEgZWwgbm9tYnJlIGRlbCBlamUgaG9yaXpvbnRhbA0KICBjb29yZF9mbGlwKCkgKyAjZ3JhZmljYSBlbiB2ZXJ0aWNhbA0KICB0aGVtZV9saWdodCgpICArICN0ZW1hIHNlbGVjY2lvbmFkbw0KICBsYWJzKHkgPSAiRnJlY3VlbmNpYSIsDQogICAgICAgeCA9ICJIYXNodGFncyIsDQogICAgICAgdGl0bGUgPSBwYXN0ZSgiSGFzaHRhZ3MgbcOhcyBmcmVjdWVudGVzIGVuIHR3ZWV0cyBwcm9waW9zIiksDQogICAgICAgc3VidGl0bGUgPSAiQ2FudGlkYWQgZGUgaGFzaHRhZ3MiLCANCiAgICAgICBjYXB0aW9uID0gIkZ1ZW50ZTogVHdpdHRlciIpDQpgYGANCg0KQSBjb250aW51YWNpw7NuLCBsb3MgaGFzaHRhZ3MgcmVsYWNpb25hZG9zIGNvbiBsb3MgcmV0d2VldHMuDQoNCmBgYHtyfQ0KdHdlZXRzX2hhc2h0YWdfciA8LSB0d2VldHNfcmV0d2VldHMgJT4lIA0KICBmaWx0ZXIoIWlzLm5hKGhhc2h0YWdzKSkgJT4lIA0KICBzZWxlY3QoaGFzaHRhZ3MpDQoNCnRpYmJsZSh3b3JkID0gdW5saXN0KHR3ZWV0c19oYXNodGFnX3IkaGFzaHRhZ3MpKSAlPiUgI2V4dHJhZXIgaGFzaHRhZw0KICBjb3VudCh3b3JkLCBuYW1lID0gImNhbnRpZGFkIiwgc29ydCA9IFRSVUUpICU+JSAjY29udGFyIGhhc2h0YWdzDQogIGhlYWQoMjApICU+JSAjc2VsZWNjaW9uYXIgbG9zIDIwIHByaW1lcm9zDQogIG11dGF0ZSh3b3JkMSA9IHJlb3JkZXIod29yZCwgY2FudGlkYWQpKSAlPiUgI29yZGVuYXINCiAgZ2dwbG90KGFlcyh4ID0gd29yZDEsIHkgPSBjYW50aWRhZCkpICsgI2NyZWFyIGxhIGdyYWZpY2ENCiAgZ2VvbV9jb2woY29sb3VyID0gIndoaXRlIiwgZmlsbCA9ICJibHVlIikgKyAjYW5hZGUgbGEgZ3LDoWZpY2EgZGUgY2FudGlkYWQNCiAgeGxhYihOVUxMKSArICNxdWl0YSBlbCBub21icmUgZGVsIGVqZSBob3Jpem9udGFsDQogIGNvb3JkX2ZsaXAoKSArICNncmFmaWNhIGVuIHZlcnRpY2FsDQogIHRoZW1lX2xpZ2h0KCkgICsgI3RlbWEgc2VsZWNjaW9uYWRvDQogIGxhYnMoeSA9ICJGcmVjdWVuY2lhIiwNCiAgICAgICB4ID0gIkhhc2h0YWdzIiwNCiAgICAgICB0aXRsZSA9IHBhc3RlKCJIYXNodGFncyBtw6FzIGZyZWN1ZW50ZXMgZW4gcmV0d2VldHMiKSwNCiAgICAgICBzdWJ0aXRsZSA9ICJDYW50aWRhZCBkZSBoYXNodGFncyIsIA0KICAgICAgIGNhcHRpb24gPSAiRnVlbnRlOiBUd2l0dGVyIikNCmBgYA0KDQpDb21vIHNlIG9ic2VydmEsIGxvcyBoYXNodGFncyBlbiBzdSBtYXlvcsOtYSBzZSBkaWZlcmVuY2lhbiBkZSB0d2VldHMgcHJvcGlvcyBjb24gcmV0d2VldHMuDQoNCiMgRnJlY3VlbmNpYSBkZSBsb3MgdHdlZXRzDQoNCk90cmEgZGVzY3JpcGNpw7NuIGludGVyZXNhbnRlIGVzIGRldGVybWluYXIgbGEgZnJlY3VlbmNpYSBlbiBxdWUgc2UgcHVibGljYS4gQSBjb250aW51YWNpw7NuLCBsYSByZXByZXNlbnRhY2nDs24gZ3LDoWZpY2EgZGUgbGEgZnJlY3VlbmNpYSBkZSB0d2VldHMgcHJvcGlvcyBwb3IgZMOtYSwgcGFyYSBlc3RvIHNlIHV0aWxpesOzIGEgKnRzX3Bsb3QqIGRlIFtydHdlZXRdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9ydHdlZXQpLCBlcyBpbXBvcnRhbnRlIG5vdGFyIHF1ZSB0YW1iacOpbiBzZSBwdWVkZSByZWFsaXphciBlc3RlIGFuw6FsaXNpcyBwb3Igc2VtYW5hLCBtZXMsIGHDsW8gc2ltcGxlbWVudGUgY2FtYmlhbmRvIGxhIHNlbGVjY2nDs24gZW4gZWwgYXJndW1lbnRvICpieSogZGUgKnRzX3Bsb3QqLg0KDQoNCmBgYHtyfQ0KbGlicmFyeShydHdlZXQpDQoNCnR3ZWV0c19wcm9waW8gJT4lIA0KICB0c19wbG90KGJ5ID0gImRheXMiLCBjb2xvciA9ICJibHVlIikgKw0KICB0aGVtZV9saWdodCgpKw0KICBsYWJzKHRpdGxlID0gIkZyZWN1ZW5jaWEgZGUgdHdlZXRzIHByb3Bpb3MiLA0KICAgICAgIHN1YnRpdGxlID0gIkNhbnRpZGFkIGRlIHR3ZWV0cyBwb3IgZMOtYSIsDQogICAgICAgeCA9ICJGZWNoYSIsDQogICAgICAgeSA9ICJDYW50aWRhZCIsDQogICAgICAgY2FwdGlvbiA9ICJGdWVudGU6IFR3aXR0ZXIiKQ0KYGBgDQoNCkRlIGZvcm1hIHNpbWlsYXIsIGxhIHJlcHJlc2VudGFjacOzbiBncsOhZmljYSBkZSBsYSBmcmVjdWVuY2lhIGRlIHJldHdlZXRzLg0KDQpgYGB7ciwgd2FybmluZz1GQUxTRX0NCnR3ZWV0c19yZXR3ZWV0cyAlPiUgDQogIHRzX3Bsb3QoYnkgPSAiZGF5cyIsIGNvbG9yID0gImJsdWUiKSArDQogIHRoZW1lX2xpZ2h0KCkrDQogIGxhYnModGl0bGUgPSAiRnJlY3VlbmNpYSBkZSByZXR3ZWV0cyIsDQogICAgICAgc3VidGl0bGUgPSAiQ2FudGlkYWQgZGUgcmV0d2VldHMgcG9yIGTDrWEiLA0KICAgICAgIHggPSAiRmVjaGEiLA0KICAgICAgIHkgPSAiQ2FudGlkYWQiLA0KICAgICAgIGNhcHRpb24gPSAiRnVlbnRlOiBUd2l0dGVyIikNCmBgYA0KDQoNCiMgUGFsYWJyYXMgbcOhcyB1c2FkYXMNCg0KT3RyYXMgZGVzY3JpcGNpb25lcyB1c3VhbGVzIHNvbiBkZXRlcm1pbmFyIGxhIGNhbnRpZGFkIGRlIHBhbGFicmFzIHV0aWxpemFkYXMsIGxhcyBwYWxhYnJhcyBtw6FzIHBvcHVsYXJlcyB5IHN1IHJlcHJlc2VudGFjacOzbi4gUGFyYSByZWFsaXphcmxhcywgZXMgaW1wb3J0YW50ZSBsaW1waWFyIGEgbG9zIGRhdG9zLCBwYXJhIGVzdG8gc2Ugc2VsZWNjaW9uw7MgYSBsb3MgcGFxdWV0ZXMgW3RpZHl0ZXh0XShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvdGlkeXRleHQvaW5kZXguaHRtbCkgeSBbdG1dKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy90bS8pLiBFbCBwcm9jZWRpbWllbnRvIGVzIGluaWNpYXIgcmVtb3ZpZW5kbyBjYXJhY3RlcmVzIHF1ZSBubyB0ZW5nYW4gdW4gc2lnbmlmaWNhZG8gY29uY3JldG8uIFNlIGhhIHNlZ3VpZG8gZWwgc2lndWllbnRlIG9yZGVuOiByZW1vdmVyIGhpcGVydsOtbmN1bG9zLCByZW1vdmVyIG1lbmNpb25lcywgcmVtb3ZlciBzZXBhcmFkb3JlcywgcmVtb3ZlciBuw7ptZXJvcyB5IHJlbW92ZXIgZXNwYWNpb3MgZW4gYmxhbmNvLiBMdWVnbywgZXMgaW1wb3J0YW50ZSByZW1vdmVyIGFjZW50b3MgeSBjYW1iaWFyIHRvZGFzIGxhcyBsZXRyYXMgYSBtaW7DunNjdWxhcyBvIG1hecO6c2N1bGFzLg0KDQpgYGB7ciwgd2FybmluZz1GQUxTRX0NCmxpYnJhcnkodGlkeXRleHQpDQpsaWJyYXJ5KHRtKQ0KDQpwYWxhYnJhcyA8LSB0d2VldHNfcHJvcGlvICU+JQ0KICBmaWx0ZXIoaXNfcmV0d2VldCA9PSBGQUxTRSkgJT4lDQogIHNlbGVjdCh0ZXh0KSAlPiUNCiAgbXV0YXRlKHRleHQ9c3RyX3JlcGxhY2VfYWxsKHRleHQsICJodHRwc1xcUyoiLCAiIikpICU+JSAjcmVtb3ZlciBoaXBlcnbDrW5jdWxvcw0KICBtdXRhdGUodGV4dD1zdHJfcmVwbGFjZV9hbGwodGV4dCwgIkBcXFMqIiwgIiIpKSAlPiUgI3JlbW92ZXIgbWVuY2lvbmVzDQogIG11dGF0ZSh0ZXh0PXN0cl9yZXBsYWNlX2FsbCh0ZXh0LCAiW1xyXG5cdF0iLCAiIikpICU+JSAjcmVtb3ZlciBzZXBhcmFkb3Jlcw0KICBtdXRhdGUodGV4dD1yZW1vdmVOdW1iZXJzKHRleHQpKSAlPiUgI3JlbW92ZXIgbsO6bWVyb3MNCiAgbXV0YXRlKHRleHQ9cmVtb3ZlUHVuY3R1YXRpb24odGV4dCkpICU+JSAjcmVtb3ZlciBwdW50dWFjaW9uDQogIG11dGF0ZSh0ZXh0PXN0cl9zcXVpc2godGV4dCkpICU+JSAjcmVtb3ZlciBlc3BhY2lvcyBlbiBibGFuY28NCiAgbXV0YXRlKHRleHQ9dG9sb3dlcih0ZXh0KSkgI2EgbWluw7pzY3VsYXMNCmBgYA0KDQpDb24gZWwgdGV4dG8gbGltcGlvLCBzZSBwcm9jZWRlIGEgcmVhbGl6YXIgbGEgdG9rZW5pemFjacOzbi4gRXN0byBzaWduaWZpY2EgcXVlIHZhbW9zIGEgZGl2aWRpciBhIGNhZGEgdHdlZXQgZW4gdW5pZGFkZXMgZGUgdGV4dG8sIGVuIGVzdGUgY2FzbyBlbiBwYWxhYnJhcy4gRXhpc3RlIHVuYSBpbnRlcmVzYW50ZSB0ZW9yw61hIGFsIHJlc3BlY3RvLCB5YSBxdWUgc2kgc2UgZGVzZWEgbGFzIHVuaWRhZGVzIHB1ZWRlbiBzZXIgZG9zIHBhbGFicmFzIHNlZ3VpZGFzIHUgb3JhY2lvbmVzLCBwb3IgZWplbXBsbywgc2kgYWxndWllbiBzZSBpbnRlcmVzYSBwdWVkZSBsZWVyIGFsIHJlc3BlY3RvIGVuIGVsIGNhcMOtdHVsbyAxIGRlIFtUZXh0IE1pbmluZyB3aXRoIFI6IEEgVGlkeSBBcHByb2FjaF0oaHR0cHM6Ly93d3cudGlkeXRleHRtaW5pbmcuY29tL3RpZHl0ZXh0Lmh0bWwpLg0KDQpgYGB7ciwgd2FybmluZz1GQUxTRX0NCnBhbGFicmFzIDwtIHBhbGFicmFzICU+JSANCiAgdW5uZXN0X3Rva2Vucyh3b3JkLCB0ZXh0LCB0b19sb3dlciA9IEYpICN0b2tlbml6YWNpb24NCg0KcGFsYWJyYXMNCmBgYA0KDQpBbCB2aXN1YWxpemFyIGxhcyBwcmltZXJhcyBwYWxhYnJhcyBvYnRlbmlkYXMgZW4gZWwgZGF0YWZyYW1lICpwYWxhYnJhcyogc2Ugb2JzZXJ2YW4gcGFsYWJyYXMgY29tbyAibGEiLCAiZGUiLCAiZXMiLCBlbnRyZSBvdHJhcywgcXVlIGxsYW1hbiBsYSBhdGVuY2nDs24geWEgcXVlIHVubyBlc3BlcmFyw61hIHF1ZSBhcGFyZXpjYW4gbXVjaGFzIHZlY2VzIGVuIHVuIGRldGVybWluYWRvIHRleHRvLiBVbmEgcHLDoWN0aWNhIGNvbcO6biBlcyByZW1vdmVyIGEgZXN0ZSB0aXBvIGRlIHBhbGFicmFzLCBkZW5vbWluYWRhcyBzdG9wd29yZHMuIEVuIGxhIGRvY3VtZW50YWNpw7NuIGRlIGxvcyBwYXF1ZXRlcyB1dGlsaXphZG9zIHNlIHB1ZWRlIGFwcmVuZGVyIHVuIHBvY28gbcOhcyBhbCByZXNwZWN0by4gRW4gZXN0ZSBjYXNvLCBhbCBjb250YXIgY29uIHVzdWFyaW9zIHF1ZSBoYWJsYW4gZXNwYcOxb2wsIGluZ2zDqXMgeSBwb3J0dWd1w6lzIHNlIHJlbW92aWVyb24gc3RvcHdvcmRzIHBhcmEgZXN0b3MgdHJlcyBpZGlvbWFzLiBBZGVtw6FzLCBzZSBjb250YWJpbGl6w7MgYSBjYWRhIHBhbGFicmEgeSBvcmRlbsOzIGVuIGZvcm1hIGRlc2NlbmRlbnRlIGNvbnNpZGVyYW5kbyBlbCBuw7ptZXJvIGRlIGFwYXJpY2lvbmVzLg0KDQpgYGB7ciwgd2FybmluZz1GQUxTRX0NCnBhbGFicmFzIDwtIHBhbGFicmFzICU+JSANCiAgZmlsdGVyKCF3b3JkICVpbiUgc3RvcHdvcmRzKCJzcGFuaXNoIikpICU+JQ0KICBmaWx0ZXIoIXdvcmQgJWluJSBzdG9wd29yZHMoInBvcnR1Z3Vlc2UiKSkgJT4lDQogIGZpbHRlcighd29yZCAlaW4lIHN0b3B3b3JkcygiZW5nbGlzaCIpKSAlPiUNCiAgY291bnQod29yZCwgc29ydCA9IFRSVUUpICU+JQ0KICBtdXRhdGUod29yZCA9IHJlb3JkZXIod29yZCwgbikpICU+JQ0KICBhcnJhbmdlKGRlc2MobikpDQoNCnBhbGFicmFzDQpgYGANCg0KT2JzZXJ2ZW1vcyBxdWUgbGFzIHBhbGFicmFzICLDqSIgeSAic2VyIiBhcGFyZWNlbiwgZXN0byBlcyBhbGdvIHF1ZSBlbiBwcmluY2lwaW8gbm8gZXNwZXJhbW9zIHN1Y2VkYSwgc2luIGVtYmFyZ28sIGFwcm92ZWNoYW1vcyBzdSBhcGFyaWNpw7NuIHBhcmEgaW5kaWNhciBjb21vIHJlbW92ZXIgcGFsYWJyYXMgZXNwZWNpYWxlcy4gU2ltcGxlbWVudGUgc2UgZGV0ZXJtaW5hIHVuIG51ZXZvIGNvbmp1bnRvIGRlIHBhbGFicmFzIGEgc2VyIHJlbW92aWRhcywgZW4gZXN0ZSBjYXNvIHNvbGFtZW50ZSBzZSBjb25zaWRlcsOzIGEgbGFzIHBhbGFicmFzIG1lbmNpb25hZGFzIGFudGVzLCBwZXJvIHNpIHNlIHRyYWJhamEgY29uIGFsZ8O6biBvdHJvIHRleHRvIHF1ZSBpbmNsdXlhIG11Y2hvcyBzw61tYm9sb3MgbyBwYWxhYnJhcyBlc3BlY2lhbGVzIGNvbW8gdmFyaWFibGVzIGNvbiBzdWLDrW5kaWNlcywgZWwgY29uc2lkZXJhciBlc3TDoSBvcGNpw7NuIHB1ZWRlIHNlciBkZSBncmFuIHV0aWxpZGFkLg0KDQpgYGB7ciwgd2FybmluZz1GQUxTRX0NCm15X3N0b3B3b3JkIDwtIHRpYmJsZSh3b3JkID0gYygiw6kiLCAic2VyIikpDQoNCnBhbGFicmFzIDwtIHBhbGFicmFzICU+JSANCiAgYW50aV9qb2luKG15X3N0b3B3b3JkKQ0KDQpwYWxhYnJhcw0KYGBgDQoNClBhcmEgZmluYWxpemFyLCBzZSBjcmXDsyB1bmEgbnViZSBkZSBwYWxhYnJhcyBxdWUgZXMgdW5hIGhlcnJhbWllbnRhIHZpc3VhbCBtdXkgYW1pZ2FibGUgcXVlIHBlcm1pdGUgZGV0ZXJtaW5hciBwb3IgZWwgdGFtYcOxbyBkZSBsYSBwYWxhYnJhIHN1IGltcG9ydGFuY2lhIHlhIHF1ZSByZXByZXNlbnRhIGFzw60gc3UgZnJlY3VlbmNpYSBkZSBhcGFyaWNpw7NuLiBQYXJhIGVzdG8gc2UgdXRpbGl6w7MgYWwgcGFxdWV0ZSBbd29yZGNsb3VkMl0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3dvcmRjbG91ZDIvKSBxdWUgY3VlbnRhIGNvbiBjYXJhY3RlcsOtc3RpY2FzIHF1ZSBwZXJtaXRlbiByZWFsaXphciBudWJlcyBtdXkgYW1pZ2FibGVzLiBQb3IgZWplbXBsbywgdXNhciB1biBmb25kbyBncmlzLCBjb2xvcmVzIHBhc3RlbCBwYXJhIGxhcyBwYWxhYnJhcyB5IGRhcmxlIHVuYSBmb3JtYSBkZSBjb3JhesOzbi4NCg0KYGBge3IsIHdhcm5pbmc9RkFMU0V9DQpsaWJyYXJ5KHdvcmRjbG91ZDIpDQpwYWxhYnJhcyAlPiUgDQogIHNlbGVjdCh3b3JkLCBmcmVxPW4pICU+JSANCiAgd29yZGNsb3VkMihzaGFwZSA9ICdjYXJkaW9pZCcsIHNpemUgPSAwLjI1LCBjb2xvciA9ICJyYW5kb20tbGlnaHQiLCBiYWNrZ3JvdW5kQ29sb3IgPSAiZ3JleSIpDQpgYGANCg0KRWwgZmluIGRlIGVzdGUgYXJjaGl2byB5IGxvcyBxdWUgdmVuZHLDoW4gZXMgY29tcGFydGlyIGxvIHF1ZSBoZSBhcHJlbmRpZG8uIEVzIHBvc2libGUgaGFjZXIgYW7DoWxpc2lzIG3DoXMgcHJvZnVuZG9zIHkgZGV0YWxsYWRvcyBxdWUgZXNwZXJvIHNlZ3VpciBjb21wYXJ0aWVuZG8sIHBvciBlamVtcGxvLCBlbCByZWFsaXphciB1biBhbsOhbGlzaXMgZGUgc2VudGltaWVudG9zIHkgdW4gY2xhc2lmaWNhZG9yIGJhc2FkbyBlbiB1biBhbsOhbGlzaXMgZGUgc2VudGltaWVudG9zLg0KDQpFbGFib3JhZG8gcG9yIEphaXJvIFJvamFzLg0K